;(function () {
    'use strict';

    var _im = window.WebIM,
        _c = _im.connection,
        _m = _im.message,
        _e = function() {},
        https = location.protocol === 'https:';

    _im.Helper = _im.utils;;
    _im.Emoji = _im.EMOTIONS = {
        path: 'static/img/faces/'
        , map: {
            '[):]': 'ee_1.png',
            '[:D]': 'ee_2.png',
            '[;)]': 'ee_3.png',
            '[:-o]': 'ee_4.png',
            '[:p]': 'ee_5.png',
            '[(H)]': 'ee_6.png',
            '[:@]': 'ee_7.png',
            '[:s]': 'ee_8.png',
            '[:$]': 'ee_9.png',
            '[:(]': 'ee_10.png',
            '[:\'(]': 'ee_11.png',
            '[:|]': 'ee_12.png',
            '[(a)]': 'ee_13.png',
            '[8o|]': 'ee_14.png',
            '[8-|]': 'ee_15.png',
            '[+o(]': 'ee_16.png',
            '[<o)]': 'ee_17.png',
            '[|-)]': 'ee_18.png',
            '[*-)]': 'ee_19.png',
            '[:-#]': 'ee_20.png',
            '[:-*]': 'ee_21.png',
            '[^o)]': 'ee_22.png',
            '[8-)]': 'ee_23.png',
            '[(|)]': 'ee_24.png',
            '[(u)]': 'ee_25.png',
            '[(S)]': 'ee_26.png',
            '[(*)]': 'ee_27.png',
            '[(#)]': 'ee_28.png',
            '[(R)]': 'ee_29.png',
            '[({)]': 'ee_30.png',
            '[(})]': 'ee_31.png',
            '[(k)]': 'ee_32.png',
            '[(F)]': 'ee_33.png',
            '[(W)]': 'ee_34.png',
            '[(D)]': 'ee_35.png'
        }
    };
    _im.Helper.EmotionPicData = (function () {
        var ems = {};

        for ( var o in _im.EMOTIONS.map ) {
            if ( _im.EMOTIONS.map.hasOwnProperty(o) ) {
                ems[o] = _im.EMOTIONS.map[o];
            }
        }
        return ems;
    }());

    _c.prototype.init = function ( options ) {
        for ( var o in options ) {
            if ( options.hasOwnProperty(o) ) {
                this[o] = options[o];
            }
        }
        this.listen(options);
    };

    var _send = function ( type, options ) {
        var msg = new _m(type);

        options.id && (msg.id = options.id);
        msg.set(options);
        options.type === 'groupchat' && msg.setGroup(options.type);
        this.send(msg.body);
    };
    _c.prototype.sendTextMessage = function ( options ) {
        _send.call(this, 'txt', options);
    };
    _c.prototype.sendPicture = function ( options ) {
        _send.call(this, 'img', options);
    };
    _c.prototype.sendAudio = function ( options ) {
        _send.call(this, 'audio', options);
    };
    _c.prototype.sendFile = function ( options ) {
        _send.call(this, 'file', options);
    };
    _c.prototype.sendLocationMessage = function ( options ) {
        _send.call(this, 'location', options);
    };
    _c.prototype.sendCmdMessage = function ( options ) {
        _send.call(this, 'cmd', options);
    };

    _c.prototype.sendPictureMessage = _e;
    _c.prototype.sendAudioMessage = _e;
    _c.prototype.sendFileMessage = _e;

    _im.Helper.innerBase64 = (function () {
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        var obj = {
            /**
             * Encodes a string in base64
             *
             * @param {String}
             *            input The string to encode in base64.
             */
            encode : function ( input ) {
                var output = "";
                var chr1, chr2, chr3;
                var enc1, enc2, enc3, enc4;
                var i = 0;

                do {
                    chr1 = input.charCodeAt(i++);
                    chr2 = input.charCodeAt(i++);
                    chr3 = input.charCodeAt(i++);

                    enc1 = chr1 >> 2;
                    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                    enc4 = chr3 & 63;

                    if ( isNaN(chr2) ) {
                        enc3 = enc4 = 64;
                    } else if ( isNaN(chr3) ) {
                        enc4 = 64;
                    }

                    output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2)
                            + keyStr.charAt(enc3) + keyStr.charAt(enc4);
                } while ( i < input.length );

                return output;
            },

            byteEncode : function ( bytes ) {
                var output = "";
                var chr1, chr2, chr3;
                var enc1, enc2, enc3, enc4;
                var i = 0;

                do {
                    chr1 = bytes[i++];
                    chr2 = bytes[i++];
                    chr3 = bytes[i++];

                    enc1 = chr1 >> 2;
                    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                    enc4 = chr3 & 63;

                    if ( isNaN(chr2) ) {
                        enc3 = enc4 = 64;
                    } else if ( isNaN(chr3) ) {
                        enc4 = 64;
                    }

                    output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2)
                            + keyStr.charAt(enc3) + keyStr.charAt(enc4);
                } while ( i < bytes.length );

                return output;
            },

            /**
             * Decodes a base64 string.
             *
             * @param {String}
             *            input The string to decode.
             */
            decode : function ( input ) {
                var output = "";
                var chr1, chr2, chr3;
                var enc1, enc2, enc3, enc4;
                var i = 0;

                // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
                input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

                do {
                    enc1 = keyStr.indexOf(input.charAt(i++));
                    enc2 = keyStr.indexOf(input.charAt(i++));
                    enc3 = keyStr.indexOf(input.charAt(i++));
                    enc4 = keyStr.indexOf(input.charAt(i++));

                    chr1 = (enc1 << 2) | (enc2 >> 4);
                    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                    chr3 = ((enc3 & 3) << 6) | enc4;

                    output = output + String.fromCharCode(chr1);

                    if ( enc3 != 64 ) {
                        output = output + String.fromCharCode(chr2);
                    }
                    if ( enc4 != 64 ) {
                        output = output + String.fromCharCode(chr3);
                    }
                } while ( i < input.length );

                return output;
            }
        };

        return obj;
    })();

    window.Easemob = window.Easemob || {};
    window.Easemob.im = window.Easemob.im || _im;
    window.Easemob.im.Connection = _c;
    window.Easemob.im.Utils = _im.utils;
    window.Easemob.im.Utils.parseEmotions = _im.utils.parseEmoji;
    window.Easemob.im.Utils.parseTextMessage = function ( message, faces ) {
        var faces = _im.Emoji;

        if ( typeof message !== 'string' ) {
            return;
        }
        if ( Object.prototype.toString.call(faces) !== '[object Object]' ) {
            return {
                isemotion: false
                , body: [
                    {
                        type: "txt"
                        , data: message
                    }
                ]
            };
        }

        var receiveMsg = message;
        var emessage = [];
        var expr = /\[[^[\]]{2,3}\]/mg;
        var emotions = receiveMsg.match(expr);

        if ( !emotions || emotions.length < 1 ){
            return {
                isemotion: false
                , body: [
                    {
                        type: "txt"
                        , data: message
                    }
                ]
            };
        }
        var isemotion = false;
        for ( var i = 0; i < emotions.length; i++ ) {
            var tmsg = receiveMsg.substring(0, receiveMsg.indexOf(emotions[i])),
                existEmotion = Easemob.im.EMOTIONS.map[emotions[i]];

            if ( tmsg ) {
                emessage.push({
                    type: "txt"
                    , data: tmsg
                });
            }
            if ( !existEmotion ) {
                emessage.push({
                    type: "txt"
                    , data: emotions[i]
                });
                continue;
            }
            var emotion = Easemob.im.EMOTIONS.map ? Easemob.im.EMOTIONS.path + existEmotion : null;

            if ( emotion ) {
                isemotion = true;
                emessage.push({
                    type: 'emotion'
                    , data: emotion
                });
            } else {
                emessage.push({
                    type: 'txt'
                    , data: emotions[i]
                });
            }
            var restMsgIndex = receiveMsg.indexOf(emotions[i]) + emotions[i].length;
            receiveMsg = receiveMsg.substring(restMsgIndex);
        }
        if ( receiveMsg ) {
            emessage.push({
                type: 'txt'
                , data: receiveMsg
            });
        }
        if ( isemotion ) {
            return {
                isemotion: isemotion
                , body: emessage
            };
        }
        return {
            isemotion: false
            , body: [
                {
                    type: "txt"
                    , data: message
                }
            ]
        };
    }
    
}());
